package Custom_generics;


import org.junit.Test;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
 *  ? 通配符的使用 ：表示任意类型，不能被实例化。与<T>类似，但也有所不同。
 *      作用：
 *      （1）只能当做泛型使用，但只能作用在变量上面，不能作用在类，接口，方法等上面：例如，List<?>，Class<?>等等
 *      （2）当某个变量使用<?>泛型时，该变量将会成为该类型变量的父类型。可以将该类型变量的任意子类赋给该变量。
 *      （3）其他不会影响任何功能
 *      特殊情况：
 *      （1）当某个集合使用<?>泛型时，该集合将不能直接进行添加元素。（因为，？表示任意类型，直接添加操作，系统将不知道该添加哪种类型数据。因此无法进行添加操作，但其他都是正常的）
 *      （2）例如： Class<T> clazz; 该clazz变量不能初始化，因为初始化时，需要具体的类字节码文件。T是不确定的，因此不能初始化
 */

/**
 * T 通配符的使用 ：表示任意未知类型，需要被实例化,不手动实例化，就会被系统默认实例为Object类型
 *      作用：
 *      （1）只能当做泛型使用，可以作用在类，接口，方法，变量等上面
 * @param <T>
 */
public class Hello<T> {
        /**
         * 通配符：？
         *
         * 类A是类B的父类，G<A>和G<B>是没有关系的，二者共同的父类是：G<?>
         */
        @Test
        public void test3() throws NoSuchMethodException {
            List<Object> list1 = new ArrayList<>();
            List<String> list2 = new ArrayList<>();
            list2.add("1");
            list2.add("2");
            list2.add("3");
            list2.add("4");

            List<T> list4 = new ArrayList<>();
            Class<?> clazz2 = String.class;
            Class<T> tClass;    //不能初始化
            //正常调用方法
            Hello<?> hello = new Hello<>();
            Hello hello1 = new Hello();
            System.out.println(hello1);
            System.out.println(hello.toString());

            //通配符集合可以作为其他任何集合的父类
            List<?> list = new ArrayList<>();
            ArrayList<?> list3 = new ArrayList<>();
//            list.add(1);  //不能直接操作通配符集合，只能通过其子类来赋值
            list.add(null); //但是null可以直接添加进去，因为null是任何引用类型的子类


            //将普通集合赋给通配符集合
            list = list1;
            list = list2;

            System.out.println("通配符集合通过索引获取值："+list.get(0));    //1
            System.out.println(list.toArray()[1]);

            //编译通过
            System.out.println("------------------------");
            print(list);
        }

        public void print(List<?> list){
            Iterator<?> iterator = list.iterator();
            while(iterator.hasNext()){
                Object obj = iterator.next();
                System.out.println(obj);
            }
        }

    @Override
    public String toString() {
        return "Hello{}";
    }
}
